/**
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
 * Licensed under the LGPL or a commercial license.
 * For LGPL see License.txt in the project root for license information.
 * For commercial licenses see https://www.tiny.cloud/
 *
 * Version: 5.8.2 (2021-06-23)
 */
(function () {
  'use strict'

  var global = tinymce.util.Tools.resolve('tinymce.PluginManager')

  var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools')

  var setDir = function (editor, dir) {
    var dom = editor.dom
    var curDir
    var blocks = editor.selection.getSelectedBlocks()
    if (blocks.length) {
      curDir = dom.getAttrib(blocks[0], 'dir')
      global$1.each(blocks, function (block) {
        if (!dom.getParent(block.parentNode, '*[dir="' + dir + '"]', dom.getRoot())) {
          dom.setAttrib(block, 'dir', curDir !== dir ? dir : null)
        }
      })
      editor.nodeChanged()
    }
  }

  var register = function (editor) {
    editor.addCommand('mceDirectionLTR', function () {
      setDir(editor, 'ltr')
    })
    editor.addCommand('mceDirectionRTL', function () {
      setDir(editor, 'rtl')
    })
  }

  var isSimpleType = function (type) {
    return function (value) {
      return typeof value === type
    }
  }
  var isNullable = function (a) {
    return a === null || a === undefined
  }
  var isNonNullable = function (a) {
    return !isNullable(a)
  }
  var isFunction = isSimpleType('function')

  var noop = function () {
  }
  var compose1 = function (fbc, fab) {
    return function (a) {
      return fbc(fab(a))
    }
  }
  var constant = function (value) {
    return function () {
      return value
    }
  }
  var never = constant(false)
  var always = constant(true)

  var none = function () {
    return NONE
  }
  var NONE = (function () {
    var eq = function (o) {
      return o.isNone()
    }
    var call = function (thunk) {
      return thunk()
    }
    var id = function (n) {
      return n
    }
    var me = {
      fold: function (n, _s) {
        return n()
      },
      is: never,
      isSome: never,
      isNone: always,
      getOr: id,
      getOrThunk: call,
      getOrDie: function (msg) {
        throw new Error(msg || 'error: getOrDie called on none.')
      },
      getOrNull: constant(null),
      getOrUndefined: constant(undefined),
      or: id,
      orThunk: call,
      map: none,
      each: noop,
      bind: none,
      exists: never,
      forall: always,
      filter: none,
      equals: eq,
      equals_: eq,
      toArray: function () {
        return []
      },
      toString: constant('none()')
    }
    return me
  }())
  var some = function (a) {
    var constant_a = constant(a)
    var self = function () {
      return me
    }
    var bind = function (f) {
      return f(a)
    }
    var me = {
      fold: function (n, s) {
        return s(a)
      },
      is: function (v) {
        return a === v
      },
      isSome: always,
      isNone: never,
      getOr: constant_a,
      getOrThunk: constant_a,
      getOrDie: constant_a,
      getOrNull: constant_a,
      getOrUndefined: constant_a,
      or: self,
      orThunk: self,
      map: function (f) {
        return some(f(a))
      },
      each: function (f) {
        f(a)
      },
      bind: bind,
      exists: bind,
      forall: bind,
      filter: function (f) {
        return f(a) ? me : NONE
      },
      toArray: function () {
        return [a]
      },
      toString: function () {
        return 'some(' + a + ')'
      },
      equals: function (o) {
        return o.is(a)
      },
      equals_: function (o, elementEq) {
        return o.fold(never, function (b) {
          return elementEq(a, b)
        })
      }
    }
    return me
  }
  var from = function (value) {
    return value === null || value === undefined ? NONE : some(value)
  }
  var Optional = {
    some: some,
    none: none,
    from: from
  }

  var isSupported = function (dom) {
    return dom.style !== undefined && isFunction(dom.style.getPropertyValue)
  }

  var fromHtml = function (html, scope) {
    var doc = scope || document
    var div = doc.createElement('div')
    div.innerHTML = html
    if (!div.hasChildNodes() || div.childNodes.length > 1) {
      console.error('HTML does not have a single root node', html)
      throw new Error('HTML must have a single root node')
    }
    return fromDom(div.childNodes[0])
  }
  var fromTag = function (tag, scope) {
    var doc = scope || document
    var node = doc.createElement(tag)
    return fromDom(node)
  }
  var fromText = function (text, scope) {
    var doc = scope || document
    var node = doc.createTextNode(text)
    return fromDom(node)
  }
  var fromDom = function (node) {
    if (node === null || node === undefined) {
      throw new Error('Node cannot be null or undefined')
    }
    return { dom: node }
  }
  var fromPoint = function (docElm, x, y) {
    return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom)
  }
  var SugarElement = {
    fromHtml: fromHtml,
    fromTag: fromTag,
    fromText: fromText,
    fromDom: fromDom,
    fromPoint: fromPoint
  }

  var Global = typeof window !== 'undefined' ? window : Function('return this;')()

  var DOCUMENT = 9
  var DOCUMENT_FRAGMENT = 11
  var TEXT = 3

  var type = function (element) {
    return element.dom.nodeType
  }
  var isType = function (t) {
    return function (element) {
      return type(element) === t
    }
  }
  var isText = isType(TEXT)
  var isDocument = isType(DOCUMENT)
  var isDocumentFragment = isType(DOCUMENT_FRAGMENT)

  var owner = function (element) {
    return SugarElement.fromDom(element.dom.ownerDocument)
  }
  var documentOrOwner = function (dos) {
    return isDocument(dos) ? dos : owner(dos)
  }

  var isShadowRoot = function (dos) {
    return isDocumentFragment(dos) && isNonNullable(dos.dom.host)
  }
  var supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode)
  var getRootNode = supported ? function (e) {
    return SugarElement.fromDom(e.dom.getRootNode())
  } : documentOrOwner
  var getShadowRoot = function (e) {
    var r = getRootNode(e)
    return isShadowRoot(r) ? Optional.some(r) : Optional.none()
  }
  var getShadowHost = function (e) {
    return SugarElement.fromDom(e.dom.host)
  }

  var inBody = function (element) {
    var dom = isText(element) ? element.dom.parentNode : element.dom
    if (dom === undefined || dom === null || dom.ownerDocument === null) {
      return false
    }
    var doc = dom.ownerDocument
    return getShadowRoot(SugarElement.fromDom(dom)).fold(function () {
      return doc.body.contains(dom)
    }, compose1(inBody, getShadowHost))
  }

  var get = function (element, property) {
    var dom = element.dom
    var styles = window.getComputedStyle(dom)
    var r = styles.getPropertyValue(property)
    return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r
  }
  var getUnsafeProperty = function (dom, property) {
    return isSupported(dom) ? dom.style.getPropertyValue(property) : ''
  }

  var getDirection = function (element) {
    return get(element, 'direction') === 'rtl' ? 'rtl' : 'ltr'
  }

  var getNodeChangeHandler = function (editor, dir) {
    return function (api) {
      var nodeChangeHandler = function (e) {
        var element = SugarElement.fromDom(e.element)
        api.setActive(getDirection(element) === dir)
      }
      editor.on('NodeChange', nodeChangeHandler)
      return function () {
        return editor.off('NodeChange', nodeChangeHandler)
      }
    }
  }
  var register$1 = function (editor) {
    editor.ui.registry.addToggleButton('ltr', {
      tooltip: 'Left to right',
      icon: 'ltr',
      onAction: function () {
        return editor.execCommand('mceDirectionLTR')
      },
      onSetup: getNodeChangeHandler(editor, 'ltr')
    })
    editor.ui.registry.addToggleButton('rtl', {
      tooltip: 'Right to left',
      icon: 'rtl',
      onAction: function () {
        return editor.execCommand('mceDirectionRTL')
      },
      onSetup: getNodeChangeHandler(editor, 'rtl')
    })
  }

  function Plugin () {
    global.add('directionality', function (editor) {
      register(editor)
      register$1(editor)
    })
  }

  Plugin()
}())
